﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.Statistics.Distribution
{
    /// <summary>
    /// This class represents a Cauchy distribution.
    /// </summary>
    [Serializable]
    public class CauchyDistribution
    {
        /// <summary>
        /// The scale parameter of the distribution.
        /// </summary>
        private readonly double scale;

        /// <summary>
        /// The location parameter of the distribution.
        /// </summary>
        private readonly double location;

        /// <summary>
        /// Initializes a new instance of the <see cref="CauchyDistribution"/> class.
        /// </summary>
        /// <param name="scale">The scale parameter of the distribution.</param>
        /// <param name="location">The location parameter of the distribution.</param>
        public CauchyDistribution(double scale, double location)
        {
            if (scale <= 0)
            {
                throw new ArgumentException("scale <= 0");
            }

            this.scale = scale;
            this.location = location;
        }

        /// <summary>
        /// Gets the scale parameter of the distribution.
        /// </summary>
        /// <value>The scale parameter of the distribution.</value>
        public double Scale
        {
            get { return this.scale; }
        }

        /// <summary>
        /// Gets the location parameter of the distribution.
        /// </summary>
        /// <value>The location parameter of the distribution.</value>
        public double Shape
        {
            get { return this.location; }
        }

        /// <summary>
        /// Gets the median of the distribution.
        /// </summary>
        /// <value>The median of the distribution.</value>
        public double Median
        {
            get { return this.location; }
        }

        /// <summary>
        /// Gets the mode of the distribution.
        /// </summary>
        /// <value>The mode of the distribution.</value>
        public double Mode
        {
            get { return this.location; }
        }

        /// <summary>
        /// Computes the probability mass function of the Cauchy distribution at the specified postion x.
        /// </summary>
        /// <param name="x">The specified position x.</param>
        /// <returns>The probability mass function of the Cauchy distribution at the specified postion x.</returns>
        public double ProbabilityMassFunction(double x)
        {
            return 1/(Math.PI*this.scale*(1 + Math.Pow((x - this.location)/this.scale, 2)));
        }

        /// <summary>
        /// Computes the cumulative distribution function of the Cauchy distribution at the specified postion x.
        /// </summary>
        /// <param name="x">The specified position x.</param>
        /// <returns>The cumulative distribution function of the Cauchy distribution at the specified postion x.</returns>
        public double CumulativeDistributionFunction(double x)
        {
            return (1/Math.PI)*Math.Atan((x - this.location)/this.scale) + 0.5;
        }
    }
}